package chatNI;

import chatController.*;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import common.*;
import java.util.logging.Level;
import java.util.logging.Logger;


/**
 * Mission: view in the MVC pattern.
 * This is the class who perform the network's interactions
  * @author bazile gaye
 */
public class ChatNI extends Observer {

	private User model;
	private ChatController cc;

	private final static int portTCPlisten = 5555;
	private UDPListen sockUDPlisten;
	private UDPCom sockUDPcom;

    /**
     * This constructor creates links between the network interface and the controller.
     * Moreover, it creates sockets will be used to communicate.
     * @param c chat controller of our system
     */
    public ChatNI(ChatController c){
		this.cc = c;
		this.model = c.getUser();
		this.model.attachNI(this);
		this.sockUDPlisten = new UDPListen();
		this.sockUDPcom = new UDPCom();

	}
	/**
	 * receive:
	 * Function use to recover messages received from sockets UDP.
         * It checks if the destination address is a broadcast destination or unicast.
         * @param mess the message received
         * @param ipAdress ip-address of destination used to send the packet
         * @return Message the message received
	 */
	protected Message receive(Message mess, InetAddress ipAdress){
            
            Boolean braodcast = false;
            try {
              
                if (ipAdress == InetAddress.getByName("255.255.255.255")){
                    braodcast = true;                    
                }
           
            } catch (UnknownHostException ex) {
                Logger.getLogger(ChatNI.class.getName()).log(Level.SEVERE, null, ex);
            }
            
            this.cc.receiveMessage(mess,braodcast);
            return mess;
	}

	/**
	 * send:
	 * Function use to send messages to sockets UDP.
         * @param ipAdress the remote user address.
         * @param mess  message sent by the local user.
	 */
	public void send(InetAddress ipAdress,Message mess){
		this.sockUDPcom.sendMessage(ipAdress,sockUDPlisten.getPortUDPlisten(), mess);
                
	}

	/**
	 * sendBroadcast:
	 * Function use to says smth to everybody connected.
         * @param mess message to send
         */
	public void sendBroadcast(Message mess){
		try {
			this.sockUDPcom.sendMessage(InetAddress.getByName("255.255.255.255"),sockUDPlisten.getPortUDPlisten(), mess);
		} catch (UnknownHostException e) {
			System.out.println("erreur dans l'envoie en broadcast");
			e.printStackTrace();
		}
		
	}
	/**
	 * connectState:
	 * Function use to update the class : open the internal sockets.
         * 
	 */
	private void connectState() throws SocketException{
		this.sockUDPlisten = new UDPListen(this);
		sockUDPlisten.start();
		this.sockUDPcom = new UDPCom(7777,this);

                Hello salut = new Hello(this.model.getUsername(), this.model.getIpAddress(), true);
		this.sendBroadcast(salut);
                
	}

	/**
	 * disconnectState:
	 * Function use to update the class : close the internal sockets.
	 */
	private void disconnectState(){
            
                Bye bye = new Bye(this.model.getIpAddress());
		this.sendBroadcast(bye);
                
		sockUDPlisten.interrupt();
		sockUDPcom.interrupt();
		sockUDPlisten = null;
		sockUDPcom = null;

	}

	/**
	 * Function not implemented.
	 */
	public void updateList() {	}


    /**
     * Fonction uses to update the system's state. 
     * Related to a modification of the model.
     */
    public void updateState() {
		if (model.getStateSystem() == true){
			try {
				this.connectState();
			} catch (SocketException e) {
				e.printStackTrace();
			}
		} else if (model.getStateSystem() == false ){
			this.disconnectState();
		}
	}

}
